package com.aepryus.loom;

import java.util.*;

public class Matrix extends Vector<Map<String,Object>> {
	private String key;
	private Map<Object,Map<String,Object>> index;

	public Matrix (String key) {
		this.key = key;
		index = new HashMap<Object,Map<String,Object>>();
	}
	public Matrix (String key,Map<String,Object>[] rows) {
		this(key);
		for (Map<String,Object> row : rows) {
			add(row);
			index.put(row.get(key), row);
		}
	}

	public Map[] getMapArray () {
		return toArray(new Map[]{});
	}

	public void put (Object key,String name,Object value) {
		Map<String,Object> row = index.get(key);
		row.put(name,value);
	}
	public Object get (Object key,Object name) {
		Map row = index.get(key);
		return row.get(name);
	}
	public void put (int i,String name,Object value) {
		Map<String,Object> row = get(i);
		row.put(name,value);
	}
	public Object get (int i,Object name) {
		Map row = get(i);
		return row.get(name);
	}

	private void merge (Map<String,Object> a,Map<String,Object> b) {
		for (String name : b.keySet()) {
			if (name.equals(key)) continue;
			Object o = a.get(name);
			if (o != null && o instanceof Number && b.get(name) != null) {
				Number x = (Number) o;
				Number y = (Number) b.get(name);
				a.put(name, x.doubleValue() + y.doubleValue());
			} else
				a.put(name, b.get(name));
		}
	}
	private void put (Map<String,Object> row) {
		Map<String,Object> old = index.get(row.get(key));
		if (old != null)
			merge(old,row);
		else {
		    add(row);
		    index.put(row.get(key),row);
		}
	}
	public Matrix append (Matrix matrix) {
		for (Map<String,Object> i : matrix)
			put(i);

		return this;
	}

	private void putWeak (Map<String,Object> row) {
		Map<String,Object> old = index.get(row.get(key));
		if (old != null)
			merge(old,row);
	}
	public Matrix appendWeak (Matrix matrix) {
		for (Map<String,Object> i : matrix)
			putWeak(i);
		return this;
	}

	public double sum (String name) {
		double x = 0;
		for (int i=0;i<size();i++)
		    x += ((Number)get(i).get(name)).doubleValue();
		return x;
	}
	public void prune (String name) {
		for (int i=0;i<size();i++) {
			double x = ((Number)get(i).get(name)).doubleValue();
			if (x == 0) {
				remove(i);
				i--;
			}
		}
	}

// Vector ======================================================================
	public String toString () {
		StringBuffer sb = new StringBuffer();

		sb.append("\r\n[ Matrix ] ===========================================\r\n");
		for (int i=0;i<size();i++) {
		    sb.append("\t");
			for (String field : get(i).keySet()) {
				Object object = get(i).get(field);
				if (object != null)
					sb.append("[").append(field).append("][").append(object.getClass().getName()).append("][").append(object).append("]");
			}
		    sb.append("\r\n");
		}
		sb.append("[ Matrix ] ===========================================\r\n");

		return sb.toString();
	}
}

